define(async () => {
    const util = await require("../util");
    const Layer = await require("Layer");
    const Node = await require("Node");

    class Scene {

        id;  //场景ID
        width;  //场景宽度
        height;  //场景高度
        childrens = [];  //场景所有子节点
        parent;  //场景的父级舞台
        
        constructor(id, options = {}) {
            util.assert(util.isString(id), new TypeError("id must be an String"));
            util.assert(util.isObject(options), new TypeError("options must be an Object"));
            const { width, height } = options;
            util.assert(util.isNumber(width), new TypeError("width must be an Number"));
            util.assert(util.isNumber(height), new TypeError("height must be an Number"));
            this.id = id;
            this.width = width;
            this.height = height;
        }

        /**
         * 场景预处理
         * 
         * 对所有子节点进行预处理，资源应该走预加载流程，后续会更改
         */
        async preprocessing() {
            await Promise.all(this.childrens.map(node => node.preprocessing()));
        }

        /**
         * 渲染场景
         */
        render() {
            this.parent.layers.forEach(layer => layer.clear());  //清除所有图层脏矩形
            this.childrens.sort((node1, node2) => node1.zIndex - node2.zIndex);  //根据子节点的zIndex调整他们的绘制顺序
            this.childrens.forEach(node => node.render());  //渲染所有子节点
            this.parent.layers.forEach(layer => layer.render());  //渲染所有图层
        }

        /**
         * 添加节点到场景并设置绘制它的图层
         * 
         * @param {Node} node 节点实例
         * @param {Layer} layer 图层实例
         * @return {Scene} 场景实例
         */
        addChild(node, layer) {
            util.assert(Node.isInstance(node), "node must be an Node instance");
            util.assert(util.isUndefined(layer) || Layer.isInstance(layer), "layer must be an Layer instance");
            node.layer = layer;
            node.parent = this;
            this.childrens.push(node);
            return this;
        }

        /**
         * 从场景移除节点
         * 
         * @param {Node} node 节点实例
         * @return {Scene} 场景实例
         */
        removeChild(node) {
            util.assert(Node.isInstance(node), "node must be an Node instance");
            const index = this.childrens.findIndex(_node => _node.layer.id === node.layer.id && _node.id === node.id);
            if(index !== -1)
                this.childrens.splice(index, 1);
            return this;
        }

        /**
         * 恢复场景动画
         */
        resume() {
            this.childrens.forEach(node => node.resume());
        }

        /**
         * 暂停场景动画
         */
        pause() {
            this.childrens.forEach(node => node.pause());
        }

        /**
         * 清除场景画面
         */
        clear() {
            if(!this.parent) return;
            this.parent.layers.forEach(layer => layer.clear());
        }

        /**
         * 销毁场景中的实例
         */
        destory() {
            this.childrens = [];
            this.parent = null;
        }

        get fps() {
            if(!this.parent) return null;
            return this.parent.fps;
        }

        /**
         * 判断是否场景实例
         * 
         * @param {Any} value 
         * @return {Boolean}
         */
        static isInstance(value) {
            return value instanceof Scene;
        }

    }

    return Scene;
});